package cn.edu.gzgs.handler;

import cn.edu.gzgs.exception.BusinessException;
import cn.edu.gzgs.vo.ApiResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 全局异常处理器, 负责将业务异常转换为携带业务错误码的HTTP响应
 * @author Zyf
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 处理自定义的业务异常 (如：用户不存在、部门下有员工无法删除等)
     * HTTP 状态码: 400 Bad Request
     * 业务状态码: 40002
     *
     * @param ex BusinessException
     * @return ResponseEntity<ApiResponse<Void>>
     */
    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<ApiResponse<Void>> handleBusinessException(BusinessException ex) {
        log.warn("业务异常: {}", ex.getMessage());
        ApiResponse<Void> response = new ApiResponse<>(40002, ex.getMessage(), null);
        return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
    }

    /**
     * 处理由 @Valid 注解触发的参数校验异常
     * HTTP 状态码: 400 Bad Request
     * 业务状态码: 40001
     *
     * @param ex MethodArgumentNotValidException
     * @return ResponseEntity<ApiResponse<String>>
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ApiResponse<String>> handleValidationException(MethodArgumentNotValidException ex) {
        // 从异常中提取第一个校验错误信息
        String message = ex.getBindingResult().getAllErrors().get(0).getDefaultMessage();
        log.warn("参数校验失败: {}", message);
        ApiResponse<String> response = new ApiResponse<>(40001, message, null);
        return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
    }

    /**
     * 处理Spring Security的权限不足异常
     * HTTP 状态码: 403 Forbidden
     * 业务状态码: 40301
     *
     * @param ex AccessDeniedException
     * @return ResponseEntity<ApiResponse<Void>>
     */
    @ExceptionHandler(AccessDeniedException.class)
    public ResponseEntity<ApiResponse<Void>> handleAccessDeniedException(AccessDeniedException ex) {
        log.warn("权限不足: {}", ex.getMessage());
        ApiResponse<Void> response = new ApiResponse<>(40301, "权限不足，无法访问此资源", null);
        return new ResponseEntity<>(response, HttpStatus.FORBIDDEN);
    }

    /**
     * 兜底处理所有其他未被捕获的异常
     * HTTP 状态码: 500 Internal Server Error
     * 业务状态码: 50000
     *
     * @param ex Exception
     * @return ResponseEntity<ApiResponse<Void>>
     */
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ApiResponse<Void>> handleAllExceptions(Exception ex) {
        log.error("服务器内部发生未知错误", ex);
        ApiResponse<Void> response = new ApiResponse<>(50000, "服务器内部错误，请联系管理员", null);
        return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
